/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author TienNT
 */
public class ServThread extends Thread {

    private String mOdbcName;
    private DatabaseAdapter daAd;
    private ServerControl.ControlThread mControlThread;
    private String mServerName;
    private Socket mSocket;
    private BufferedReader mFromClient;
    private PrintWriter mToClient;
    public static int count = 1;
    public static Hashtable<String, ServThread> mSocketTable = new Hashtable<>();

    public ServThread(ServerControl.ControlThread controlThread, Socket socket, String OdbcName) throws SQLException {
        mOdbcName=OdbcName;
        daAd = new DatabaseAdapter(mOdbcName);
        mSocket = socket;
        mControlThread = controlThread;
        mServerName = "Server thread " + this.count++;
        mControlThread.appendLog(mServerName + ":   " + "start...");
    }

    public PrintWriter getToClientStream() {
        return mToClient;
    }

    @Override
    public void run() {
        String temp1, temp2, username, password;
        String[] strings;
        ResultSet rs;
        SimpleMD5 md = new SimpleMD5();
        // TODO Auto-generated method stub
        try {
            mFromClient = new BufferedReader(new InputStreamReader(
                    mSocket.getInputStream()));
            mToClient = new PrintWriter(mSocket.getOutputStream(), true);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            mControlThread.appendLog(mServerName + ":   " + "Error...");
            mControlThread.appendLog(e.getMessage());
        }
        try {
            while (true) {
                final String s = mFromClient.readLine();
                int request = Integer.parseInt(s.charAt(0) + "");
                switch (request) {
                    case ClientUtils.REQUEST_LOGIN:
                        // Login request
                        temp1 = null;
                        temp2 = null;
                        strings = s.split(":");
                        username = strings[1];
                        mControlThread.appendLog(username + " has connected.");
                        password = strings[2];
                        try {

                            temp1 = md.MD5(password);
                            System.out.printf("temp1 " + temp1);
                            rs = daAd.executeQuery("select * from userinfo where username='" + username + "'");
                            if (rs.next()) {
                                temp2 = rs.getString(2);
                                System.out.println("temp2" + temp2);
                            }
                            if (temp1.equals(temp2) && temp1 != null) {
                                mSocketTable.put(username, this);
                                mToClient.println("" + ClientUtils.ACCEPT);
                                mControlThread.appendLog(username + " login successfully!");
                                // Transfer contact list
                                notifyContactListChanged();
                                break;
                            } else {
                            }
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        } finally {
                            mToClient.println("" + ClientUtils.NOT_ACCEPT);
                            break;
                        }

                    case ClientUtils.REQUEST_LOGOUT:
                        String nameOfClient = s.substring(2);
                        mControlThread.appendLog(nameOfClient + " request to logout.");
                        mSocketTable.remove(nameOfClient);
                        mControlThread.appendLog(nameOfClient + " has loged out!");
                        notifyContactListChanged();
                        mFromClient.close();
                        mToClient.close();
                        mSocket.close();
                        return;

                    case ClientUtils.NEW_MESSAGE:
                        // Client minh yeu cau gui toi 1 client khac.
                        String[] s2 = s.split(":");
                        String desClient = s2[2];
                        ServThread servThread = mSocketTable.get(desClient);
                        servThread.getToClientStream().println(s);
                        break;

                    case ClientUtils.REQUEST_REGISTER:
                        strings = s.split(":");
                        username = strings[1];
                        password = strings[2];
                        mControlThread.appendLog(username+ "Request register");
                        try {
                            rs = daAd.executeQuery("select * from userinfo where username='" + username + "'");
                            if (!rs.next()) {
                                temp1 = md.MD5(password);
                                daAd.executeUpdate("insert into userinfo values('" + username + "','" + temp1 + "','')");
                                mToClient.println("" + ClientUtils.ACCEPT);
                                break;
                            } else {
                                mToClient.println("" + ClientUtils.NOT_ACCEPT);
                                break;
                            }

                        } catch (NoSuchAlgorithmException | UnsupportedEncodingException | ClassNotFoundException | SQLException ex) {
                            Logger.getLogger(ServThread.class.getName()).log(Level.SEVERE, null, ex);
                            mToClient.println("" + ClientUtils.ACCEPT);
                            break;
                        }finally{
                            break;
                        }
                    case ClientUtils.REQUEST_CHANGEPASSWORD:
                        strings = s.split(":");
                        username = strings[1];
                        password = strings[2];
                        String newpassword = strings[3];
                        temp1 = md.MD5(password);
                        mControlThread.appendLog(username + "Request change password");
                        try {
                            rs = daAd.executeQuery("select * from userinfo where username='" + username + "' and password='"+temp1+"'");
                            if (!rs.next()) {
                                mToClient.println("" + ClientUtils.NOT_ACCEPT);
                                break;
                            }
                            else{
                                temp2=md.MD5(newpassword);
                                daAd.executeUpdate("update userinfo set password='"+temp2+"' where username='"+username+"'");
                                mToClient.println("" + ClientUtils.ACCEPT);
                                 
                            }

                        } catch (ClassNotFoundException | SQLException ex) {
                            Logger.getLogger(ServThread.class.getName()).log(Level.SEVERE, null, ex);
                            //mToClient.println("" + ClientUtils.NOT_ACCEPT);
                        }


                    default:
                        break;
                }
            }

        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(ServThread.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(ServThread.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            mControlThread.appendLog(mServerName + ":   " + "Error...");
            mControlThread.appendLog(ex.getMessage());
        }
    }

    public void notifyContactListChanged() {
        Enumeration<ServThread> servThreadList = mSocketTable.elements();

        int size = mSocketTable.size();
        while (servThreadList.hasMoreElements()) {
            ServThread servThread = (ServThread) servThreadList.nextElement();
            PrintWriter out = servThread.getToClientStream();
            out.println("" + ClientUtils.CONTACT_LIST_CHANGED);
            out.println("" + size);
            Enumeration<String> contactList = mSocketTable.keys();
            while (contactList.hasMoreElements()) {
                out.println((String) contactList.nextElement());
            }
        }
    }
}
